package com.zxjbyte.yiyi.framework.common.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.util.NumberUtil;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.RoundingMode;

/**
 * 图片压缩工具类
 *
 * @Author zhangxingjia
 * @Date 2025/10/13 14:35
 * @Version: 1.0
 */
@Slf4j
@UtilityClass
public class ImageCompressUtil {

    // 控制图片 体积与性能平衡
    private final long MAX_FILE_SIZE_KB = 150; // 150KB

    /**
     * 智能压缩图片 - 只在需要时压缩
     *
     *  用于Excel 导出图片时压缩
     */
    public byte[] smartCompressExcelImage(byte[] imageData, String fileName) {
        if (imageData == null || imageData.length == 0) {
            return imageData;
        }
        try {
            // 检查文件大小
            double fileSizeKB = NumberUtil.div(imageData.length, 1024, 1, RoundingMode.DOWN);
            if (fileSizeKB <= MAX_FILE_SIZE_KB) {
                return imageData;
            }

            // 转换为BufferedImage检查尺寸
            BufferedImage originalImage = ImgUtil.toImage(imageData);
            if (originalImage == null) {
                return imageData;
            }

            int originalWidth = originalImage.getWidth();
            int originalHeight = originalImage.getHeight();
            boolean isPortrait = originalHeight > originalWidth;

            // 按方向区分最大尺寸
            int maxWidth = isPortrait ? 900 : 1000;
            int maxHeight = isPortrait ? 1200 : 700;

            // 判断是否需要压缩
            if (originalWidth <= maxWidth && originalHeight <= maxHeight) {
                return imageData;
            }
            long startTime = System.currentTimeMillis();
            log.info("--> [{}] 开始压缩图片: {}x{}，文件大小 {}KB", fileName, originalWidth, originalHeight, fileSizeKB);

            // 计算缩放比例
            double scale = Math.min(
                    (double) maxWidth / originalWidth,
                    (double) maxHeight / originalHeight
            );
            scale = Math.min(scale, 1.0); // 确保不放大

            int targetWidth = (int) (originalWidth * scale);
            int targetHeight = (int) (originalHeight * scale);

            // 判断原图是否有透明通道
            boolean hasAlpha = originalImage.getColorModel().hasAlpha();

            // 按比例缩放图片
            Image scaled = ImgUtil.scale(originalImage, targetWidth, targetHeight, hasAlpha ? null : Color.WHITE);

            // 默认压缩质量（0~1，JPEG 有效）
            float quality = isPortrait ? 0.9f : 0.85f;
            // 执行压缩输出
            byte[] compressed = compressToBytes(scaled, originalImage.getType(), quality);

            double afterKB = NumberUtil.div(compressed.length, 1024, 1, RoundingMode.DOWN);
            log.info("<-- [{}] 图片压缩结果: {}x{} → {}x{} ({}KB → {}KB)，耗时：{}毫秒",
                    fileName, originalWidth, originalHeight, targetWidth, targetHeight, fileSizeKB, afterKB, DateUtil.spendMs(startTime));

            return compressed;

        } catch (Exception e) {
            log.error("智能压缩失败，返回原图: {}", e.getMessage(), e);
            return imageData;
        }

    }


    /**
     * 使用指定质量压缩图片输出字节数组
     */
    private byte[] compressToBytes(Image image, int imageType, float quality) throws IOException {
        BufferedImage buffered = ImgUtil.toBufferedImage(image, imageType);
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        // 根据图片类型动态判断文件格式
        String format = (imageType == BufferedImage.TYPE_INT_ARGB) ? "png" : "jpeg";

        // 写出图片到输出流
        if ("png".equalsIgnoreCase(format)) {
            // 对于 PNG，直接无损保存
            ImgUtil.write(buffered, format, out);
        } else {
            // 对于 JPEG，进行压缩操作
            ImageOutputStream imageOutputStream = ImgUtil.getImageOutputStream(out);
            ImgUtil.write(buffered, format, imageOutputStream, quality);  // 质量压缩
        }
        return out.toByteArray();
    }
}
